package com.zy.mc_module.utils.retrofit;

import android.webkit.WebSettings;

import com.jakewharton.retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory;
import com.zy.mc_module.BuildConfig;
import com.zy.mc_module.base.App;
import com.zy.mc_module.common.Constant;
import com.zy.mc_module.mvp.bean.TokenBean;
import com.zy.mc_module.utils.AppTools;
import com.zy.mc_module.utils.GsonUtil;
import com.zy.mc_module.utils.Logs;
import com.zy.mc_module.utils.NetUtil;
import com.zy.mc_module.utils.SPUtil;
import com.zy.mc_module.utils.StringsUtils;
import com.zy.mc_module.utils.SystemUtil;

import okhttp3.*;
import okhttp3.logging.HttpLoggingInterceptor;
import retrofit2.Retrofit;
import retrofit2.converter.gson.GsonConverterFactory;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.security.GeneralSecurityException;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.cert.Certificate;
import java.security.cert.CertificateFactory;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.concurrent.TimeUnit;

import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.TrustManager;
import javax.net.ssl.TrustManagerFactory;
import javax.net.ssl.X509TrustManager;

/**
 * Created on 18/10/22
 * 网络请求工具类
 */
public class RetrofitManager {
    private static String TAG = "RetrofitManager";
    private Retrofit retrofit;
    private long time = 38L;

    private static class RetrofitInstance {
        private static final RetrofitManager INSTANCE = new RetrofitManager();
    }

    public static RetrofitManager getInstance() {
        return RetrofitInstance.INSTANCE;
    }

    /***
     * 设请求头
     */
    private static class addHeaderInterceptor implements Interceptor {
        @Override
        public Response intercept(Chain chain) throws IOException {
            Request original = chain.request();
            Request.Builder requestBuilder = original.newBuilder()
                    //.addHeader("equipment", "android")
                    .removeHeader("User-Agent")//移除旧的
                    .addHeader("User-Agent", WebSettings.getDefaultUserAgent(App.getInstance()))//添加真正的头部
                    //.addHeader("uuid", Settings.System.getString(App.getAppContext().getContentResolver(), Settings.Secure.ANDROID_ID))
                    .addHeader("versionNumber", SystemUtil.getVerName(App.getAppContext()));
            String tokenInfo = SPUtil.getString(Constant.USER_TOKEN_INFO, "");
            if (!StringsUtils.isEmpty(tokenInfo)) {
                TokenBean bean = GsonUtil.gsonToBean(tokenInfo,TokenBean.class);
                requestBuilder.addHeader("Authorization", bean.getToken_type() + " " + bean.getAccess_token());
            }
            //从request中获取原有的HttpUrl实例oldHttpUrl
            HttpUrl oldHttpUrl = original.url();
            //从request中获取headers，通过给定的键url_type
            List<String> headerValues = original.headers("url_type");
            if (headerValues != null && headerValues.size() > 0) {
                //如果有这个header，先将配置的header删除，因此header仅用作app和okhttp之间使用
                requestBuilder.removeHeader("url_type");
                //匹配获得新的BaseUrl
                String headerValue = headerValues.get(0);
                HttpUrl newBaseUrl = null;
                if ("launcher".equals(headerValue)) {
                    newBaseUrl = HttpUrl.parse(AppTools.Base_Url);
                } else {
                    newBaseUrl = oldHttpUrl;
                }
                //重建新的HttpUrl，修改需要修改的url部分
                HttpUrl newFullUrl = oldHttpUrl
                        .newBuilder()
                        .scheme(newBaseUrl.scheme())//更换网络协议
                        .host(newBaseUrl.host())//更换主机名
                        .port(newBaseUrl.port())//更换端口
//                            .removePathSegment(0)//移除第一个参数
                        .build();
                //重建这个request，通过builder.url(newFullUrl).build()；
                // 然后返回一个response至此结束修改
                return chain.proceed(requestBuilder.url(newFullUrl).build());
            }
            Request request = requestBuilder.build();
            return chain.proceed(request);
        }
    }

    /***
     * 设置缓存
     * 只对get有用,post没有缓存
     */
    private class CacheInterceptor implements Interceptor {
        public Response intercept(Chain chain) throws IOException {
            Request request = chain.request();
            //判断是否有网络
            if (NetUtil.isNetwork()) {
                Response response = chain.proceed(request);
                //有网的时候读接口上的@Headers里的配置，你可以在这里进行统一的设置
                String cacheControl = request.cacheControl().toString();
                int maxAge = 0;//有网时缓存时间
                if (cacheControl.length() > 0) {
                    return response.newBuilder()
                            .header("Cache-Control", cacheControl)
                            .removeHeader("Pragma")
                            .build();
                } else {
                    return response.newBuilder()
                            .removeHeader("Pragma")
                            .removeHeader("Cache-Control")
                            .header("Cache-Control", "public, max-age=" + maxAge)
                            .build();
                }
            } else {
                //无网络时,设置缓存超时时间为 10天,只对get有用,post没有缓存
                request = request.newBuilder()
                        .cacheControl(CacheControl.FORCE_CACHE)
                        .build();
                Response response = chain.proceed(request);
                int maxStale = 60 * 60 * 24 * 5;
                return response.newBuilder()
                        .removeHeader("Pragma")
                        .removeHeader("Cache-Control")
                        .header("Cache-Control", "public, only-if-cached, max-stale=" + maxStale)
                        .build();
            }
        }
    }

    /***
     * 定义拦截器中的网络日志工具
     */
    private static class HttpLogger implements HttpLoggingInterceptor.Logger {
        public void log(String message) {
            int maxLength = 1365;//1024*4/3≈1365
            int count = message.length();
            if (maxLength >= count) {
                Logs.Log_d("Okhttp", message);
            } else {
                while (maxLength < message.length()) {
                    String temp = message.substring(0, maxLength);
                    Logs.Log_d("Okhttp", temp + "\n\n");
                    message = message.replace(temp, "");
                }
                Logs.Log_d("Okhttp", message);
            }
        }
    }

    /***
     * 创建Retrofit实例
     */
    private Retrofit getRetrofit() {
        if (retrofit == null) {
            synchronized (RetrofitManager.class) {
                if (retrofit == null) {
                    //拦截器
                    HttpLoggingInterceptor loggingInterceptor = new HttpLoggingInterceptor(new HttpLogger());
                    if (BuildConfig.DEBUG) {
                        loggingInterceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
                    }else {
                        loggingInterceptor.setLevel(HttpLoggingInterceptor.Level.NONE);
                    }
                    //缓存
                    File file = new File(App.getInstance().getCacheDir(), "mc_cache");
                    Cache cache = new Cache(file, 1024 * 1024 * 200);
                    //设置OkhtpClient
                    OkHttpClient client = new OkHttpClient().newBuilder()
                            .addNetworkInterceptor(loggingInterceptor)
                            .addInterceptor(new CacheInterceptor())
                            .addInterceptor(new addHeaderInterceptor())//添加头
                            .addNetworkInterceptor(new CacheInterceptor())
                            .cache(cache)
                            //.sslSocketFactory(context.getSocketFactory(), trustManager)
                            //.hostnameVerifier(new TrustAllHostnameVerifier())
                            .connectTimeout(time, TimeUnit.SECONDS)
                            .readTimeout(time, TimeUnit.SECONDS)
                            .writeTimeout(time, TimeUnit.SECONDS)
                            .build();
                    //获取Retrofit实例
                    if (null == AppTools.Base_Url) {
                        AppTools.Base_Url = AppTools.APP_URL_PRETEST;
                    }
                    retrofit = new Retrofit.Builder().baseUrl(AppTools.Base_Url).client(client)
                            .addConverterFactory(GsonConverterFactory.create())
                            .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
                            .build();
                }
            }
        }
        return retrofit;
    }

    /***
     * 创建网络接口请求实例
     */
    public ApiService getApi() {
        return getRetrofit().create(ApiService.class);
    }

    private X509TrustManager fun(InputStream in) throws GeneralSecurityException {
        CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509");
        Collection<? extends Certificate> certificates = certificateFactory.generateCertificates(in);
        if (certificates.isEmpty()) {
            throw new IllegalArgumentException("expected non-empty set of trusted certificates");
        }
        char[] password = "password".toCharArray();
        KeyStore keyStore = null;
        try {
            keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
            keyStore.load(null, password);
        } catch (NoSuchAlgorithmException | KeyStoreException e) {
            e.printStackTrace();
        } catch (IOException e) {
            throw new AssertionError(e);
        }
        int index = 0;
        for (Certificate certificate : certificates) {
            String certificateAlias = Integer.toString(index++);
            keyStore.setCertificateEntry(certificateAlias, certificate);
        }

        KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
        keyManagerFactory.init(keyStore, password);
        TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
        trustManagerFactory.init(keyStore);
        TrustManager[] trustManagers = trustManagerFactory.getTrustManagers();
        if (trustManagers.length != 1 || !(trustManagers[0] instanceof X509TrustManager)) {
            throw new IllegalStateException("Unexpected default trust managers:" + Arrays.toString(trustManagers));
        }
        return (X509TrustManager) trustManagers[0];
    }
}
